<?php


namespace app\api\service;


use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;

class UserToken extends Token
{
    protected $code;
    protected $wxAppId;
    protected $wxAppSecret;
    protected $wxLogUrl;

    function __construct($code = '')
    {
        $this->code = $code;
        $this->wxAppId = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        $this->wxLogUrl = sprintf(config('wx.login_url'), $this->wxAppId, $this->wxAppSecret, $this->code);
    }

    //获取令牌
    public function get()
    {
        $rerult = curl_get($this->wxLogUrl);
        $wsRerult = json_decode($rerult, true);
        if (empty($wsRerult)) {
            throw new Exception('微信appid或者appsecrect错误');
        } elseif (array_key_exists('errcode', $wsRerult)) {
            //errmsg
            $this->processloginError($wsRerult);
        } else {
            return $this->grantToken($wsRerult);
        }
    }

    private function grantToken($wsRerult)
    {
//        获取用户openid
        $openid = $wsRerult['openid'];
        $user = UserModel::getUserByOpenId($openid);
        if ($user) {
            $uid = $user->id;
        } else {
            $uid = $this->newUser($openid)->id;
        }
        $cachedValue = $this->prepareCachedValue($wsRerult, $uid);
        $token = $this->saveToCache($cachedValue);
        return $token;
    }

    private function newUser($openid)
    {
        $result = UserModel::create([
            'openid' => $openid
        ]);
        return $result;
    }

    private function saveToCache($cachedValue)
    {
        $key = $this->generateToken();
        $value = $cachedValue;
        $expire = config('setting.token_expire_in');
        $request = cache($key, $value, $expire);
        if (!$request) {
            throw new TokenException([
                'msg' => '服务器缓存异常',
                'errorCode' => 10005
            ]);
        }
        return $key;
    }

    private function prepareCachedValue($wsRerult, $uid)
    {
        $cachedValue = $wsRerult;
        $cachedValue['uid'] = $uid;
        //scope权限控制
        $cachedValue['scope'] = 16;
        return $cachedValue;
    }

    private function processloginError($wsRerult)
    {
        throw new WeChatException([
            'msg' => $wsRerult['errmsg'],
            'errorCode' => $wsRerult['errcode']
        ]);
    }
}